package com.mingchuang.etc2.util;


import java.io.UnsupportedEncodingException;
import java.nio.ByteBuffer;

/**
 * - @Description:  数据转换类
 * - @Author:  LXJ
 * - @Time:  2019/4/24 15:03
 */
public class ConvertUtil {
    private static final String Charset = "UTF-8";
    public static final String GB18030 = "GB18030";
    public static final String ISO8859_1 = "ISO-8859-1";

    /**
     * 获取byte的值，范围是0~255
     *
     * @param b
     * @return
     */
    public static int getByteValue(byte b) {
        return b & 0xff;
    }

    public static byte int2Byte(int intData) {
        return (byte) intData;
    }

    /**
     * <p>
     * short转byte[],数组从左到右，高位到低位
     * </p>
     * 由于java没有unsigned类型，所以用int存short的值
     *
     * @param shortData
     * @return byte[]:byteData
     */
    public static byte[] short2bytes(int shortData) {
        byte[] byteData = new byte[2];
        for (int i = 0; i < 2; i++) {
            int offset = i * 8;
            byteData[i] = (byte) (shortData >> offset);
        }
        reversalBytes(byteData);
        return byteData;
    }

    /**
     * int转byte[],数组从左到右，数组从左到右，高位到低位
     *
     * @param intData
     * @return byte[]:byteData
     */
    public static byte[] int2bytes(int intData) {
        byte[] byteData = new byte[4];
        for (int i = 0; i < 4; i++) {
            int offset = i * 8;
            byteData[i] = (byte) (intData >> offset);
        }
        reversalBytes(byteData);
        return byteData;
    }

    /**
     * long转byte[],数组从左到右，数组从左到右，高位到低位
     *
     * @param longData
     * @return byte[]:byteData
     */
    public static byte[] long2bytes(long longData) {
        byte[] byteData = new byte[8];
        for (int i = 0; i < 8; i++) {
            int offset = i * 8;
            byteData[i] = (byte) (longData >> offset);
        }
        reversalBytes(byteData);
        return byteData;
    }

    /**
     * bytes转short,数组从左到右，依次是高位到低位
     *
     * @param bytes
     * @return short
     */
    public static short bytes2short(byte[] bytes) {
        short shortData = 0;
        int len = bytes.length <= 2 ? bytes.length : 2;
        for (int i = 0; i < len; i++) {
            shortData <<= 8;
            shortData |= (bytes[i] & 0xff);
        }
        return shortData;
    }

    /**
     * bytes转int,数组从左到右，依次是高位到低位
     *
     * @param bytes
     * @return int
     */
    public static int bytes2int(byte[] bytes) {
        int intData = 0;
        int len = bytes.length <= 4 ? bytes.length : 4;
        for (int i = 0; i < len; i++) {
            intData <<= 8;
            intData |= (bytes[i] & 0xff);
        }
        return intData;
    }

    /**
     * bytes中选取少于等4个字节转int
     *
     * @param bytes 包含int字节的数组
     * @param start int字节在数组中起始index
     * @param len   int字节长度 不可大于8
     * @return 如果起始start加上len大于bytes长度将返回-1
     */
    public static int bytes2int(byte[] bytes, int start, int len) {
        int intData = 0;
        int length = len <= 4 ? start + len : start + 4;
        if (length > bytes.length) {
            return -1;
        }
        for (int i = start; i < length; i++) {
            intData <<= 8;
            intData |= (bytes[i] & 0xff);
        }
        return intData;
    }

    /**
     * bytes转long
     *
     * @param bytes 数组从左到右，依次是高位到低位
     * @return long
     */
    public static long bytes2long(byte[] bytes) {
        long longData = 0;
        int len = bytes.length <= 8 ? bytes.length : 8;
        for (int i = 0; i < len; i++) {
            longData <<= 8;
            longData |= (bytes[i] & 0xff);
        }
        return longData;
    }

    /**
     * bytes中选取少于等8个字节转long
     *
     * @param bytes 包含long字节的数组
     * @param start long字节在数组中起始index
     * @param len   long字节长度 不可大于8
     * @return 如果起始start加上len大于bytes长度将返回-1
     */
    public static long bytes2long(byte[] bytes, int start, int len) {
        long longData = 0;
        int length = len <= 8 ? start + len : start + 8;
        if (length > bytes.length)
            return -1;
        for (int i = start; i < length; i++) {
            longData <<= 8;
            longData |= (bytes[i] & 0xff);
        }
        return longData;
    }

    /**
     * bytes转String
     *
     * @param bytes
     * @return
     * @throws UnsupportedEncodingException
     */
    public static String bytes2string(byte[] bytes) {
        if (bytes == null) {
            return "";
        }
        String newStr = null;
        try {
            newStr = new String(bytes, GB18030).trim();
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        }
        return newStr;
    }

    /**
     * bytes转String
     *
     * @param bytes
     * @param charset
     * @return
     * @throws UnsupportedEncodingException
     */
    public static String bytes2string(byte[] bytes, String charset) {
        if (bytes == null) {
            return "";
        }
        String newStr = null;
        try {
            newStr = new String(bytes, charset).trim();
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        }
        return newStr;
    }

    /**
     * bytes中指定子数组转String
     *
     * @param bytes
     * @param charset
     * @param start
     * @param len
     * @return
     */
    public static String bytes2string(byte[] bytes, String charset, int start, int len) {
        if (bytes == null) {
            return "";
        }
        if (start + len > bytes.length) {
            len = bytes.length - start;
        }
        String newStr = null;
        try {
            byte[] tmp = new byte[len];
            System.arraycopy(bytes, start, tmp, 0, len);
            newStr = new String(tmp, Charset).trim();
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        }
        return newStr;
    }

    /**
     * String转bytes
     *
     * @param str
     * @return
     * @throws UnsupportedEncodingException
     */
    public static byte[] string2bytes(String str) {
        if (str == null) {
            return null;
        }
        try {
            return str.getBytes(Charset);
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
            return null;
        }
    }

    /**
     * String转bytes
     *
     * @param str
     * @param charset
     * @return
     * @throws UnsupportedEncodingException
     */
    public static byte[] string2bytes(String str, String charset) {
        if (str == null) {
            return null;
        }
        try {
            return str.getBytes(charset);
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
            return null;
        }
    }

    /**
     * 将byte转化成16进制的字符串 byte=10,String=0a
     *
     * @param b
     * @return String hex
     */
    public static String byte2hex(byte b) {
        int value = b & 0xff;
        String hexVaule = Integer.toHexString(value);
        if (hexVaule.length() < 2) {
            hexVaule = "0" + hexVaule;
        }
        return hexVaule;
    }

    /**
     * 将byte[]转化成16进制的字符串 byte[]=10,11,12,String=0a0b0c
     *
     * @param bytes
     * @return String hex
     */
    public static String bytes2hex(byte[] bytes) {
        String hex = "";
        for (int i = 0; i < bytes.length; i++) {
            int value = bytes[i] & 0xff;
            String hexVaule = Integer.toHexString(value);
            if (hexVaule.length() < 2) {
                hexVaule = "0" + hexVaule;
            }
            hex += hexVaule;
        }
        return hex;
    }

    /**
     * 将byte[] 指定子数组转化成16进制的字符串 byte[]=10,11,12,String=0a0b0c
     *
     * @param bytes
     * @param start 子数组起始位置
     * @param len   子数组长度
     * @return
     */
    public static String bytes2hex(byte[] bytes, int start, int len) {
        String hex = "";
        int length = start + len;
        if (length > bytes.length) {
            return hex;
        }

        for (int i = start; i < length; i++) {
            int value = bytes[i] & 0xff;
            String hexVaule = Integer.toHexString(value);
            if (hexVaule.length() < 2) {
                hexVaule = "0" + hexVaule;
            }
            hex += hexVaule;
        }
        return hex;
    }

    /**
     * byte[]=10,11,12,String=0a0b0c 将16进制的字符串转为byte数组，如果hex的长度不是偶数，则首位补0
     *
     * @param hex
     * @return
     */
    public static byte[] hex2bytes(String hex) {
        if (hex == null || hex.length() < 1) {
            return null;
        }

        // 如果长度不是偶数，则前面补0
        if (hex.length() % 2 != 0) {
            hex = "0" + hex;
        }

        byte[] bytes = new byte[(hex.length() + 1) / 2];

        try {
            for (int i = 0, j = 0; i < hex.length(); i += 2) {
                byte hight = (byte) (Character.digit(hex.charAt(i), 16) & 0xff);
                byte low = (byte) (Character.digit(hex.charAt(i + 1), 16) & 0xff);
                bytes[j++] = (byte) (hight << 4 | low);
            }
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }

        return bytes;
    }

    /**
     * byte[]转为坐标类型,先转为int，再除以10^6
     * <p>
     * 这里的坐标数据只支持4byte，坐标有正负数
     * </p>
     *
     * @param bytes
     * @return
     */
    public static double bytes2Coordinate(byte[] bytes) {
        double d = 0;
        long l = bytes2int(bytes);
        d = l / 1000000.0;
        return d;
    }

    /**
     * <p>
     * 将src的内容复制到dest中
     * </p>
     * <ul>
     * <li>如果src为null，则dest也为null</li>
     * <li>如果dest为null或者dest.length&lt;src.length，则dest=new byte[src.length]</li>
     * </ul>
     *
     * @param src  要复制的byte[]
     * @param dest 复制的目标byte[]
     */
    public static void copyBytes(byte[] src, byte[] dest) {
        if (src == null) {
            dest = null;
        }
        if (dest == null || dest.length < src.length) {
            dest = new byte[src.length];
        }
        System.arraycopy(src, 0, dest, 0, src.length);
    }

    /**
     * <p>
     * 将appendBytes追加到oldBytes后面
     * <ul>
     * <li>1.如果appendBytes为null，则直接返回oldBytes</li>
     * <li>2.如果oldBytes为null，则直接返回appendBytes</li>
     * </ul>
     * </p>
     *
     * @param oldBytes    原数据
     * @param appendBytes 需要追加的数据
     * @return
     */
    public static byte[] appendBytes(byte[] oldBytes, byte[] appendBytes) {
        if (appendBytes == null) {
            return oldBytes;
        }

        if (oldBytes == null) {
            return appendBytes;
        }

        int len = 0;
        // 计算合并后的长度
        len = oldBytes.length + appendBytes.length;
        // 申请合并后的内存空间
        byte[] bytes = new byte[len];
        System.arraycopy(oldBytes, 0, bytes, 0, oldBytes.length);
        System.arraycopy(appendBytes, 0, bytes, oldBytes.length, appendBytes.length);
        return bytes;
    }

    /**
     * 获得short类型数据的无符号值
     *
     * @param data
     * @return
     */
    public static int getUnsignedShort(short data) {
        return data & 0xffff;
    }

    /**
     * 获得int类型的unsigned值
     */
    public static long getUnsignedInt(int data) {
        return data & 0xffffffffl;
    }

    /**
     * 翻转byte数组
     *
     * @param bytes
     */
    public static void reversalBytes(byte[] bytes) {
        byte b = 0;
        int length = bytes.length;
        int half = length / 2;
        for (int i = 0; i < half; i++) {
            b = bytes[i];
            bytes[i] = bytes[length - 1 - i];
            bytes[length - 1 - i] = b;
        }
    }

    /**
     * 截取数据
     *
     * @param data  要截取的源数据
     * @param start 开始截取位置(包含该点数据)
     * @param end   截取结束位置(包含该点数据)
     * @return
     */
    public static byte[] getSubData(byte[] data, int start, int end) {
        int length = end - start + 1;
        return getDataSequence(data, start, length);
    }

    /**
     * 获取子串
     *
     * @param data  要获取子串的原始数据
     * @param start 开始位置，包含改节点
     * @param len   要截取的子串长度
     * @return
     */
    public static byte[] getDataSequence(byte[] data, int start, int len) {
        byte[] returnData = new byte[len];
        System.arraycopy(data, start, returnData, 0, len);
        return returnData;
    }

    /*******************************************(转为16进制)******************************************************/

    /**
     * string转16进制
     *
     * @return
     */
    public static String stringToHex(String str) {
        String hex;
        byte[] bytes = string2bytes(str, GB18030);
        hex = bytes2hex(bytes);
        return hex;
    }

    /**
     * string转16进制
     *
     * @return
     */
    public static String stringToHex(String str, String charset) {
        String hex;
        byte[] bytes = string2bytes(str, charset);
        hex = bytes2hex(bytes);
        return hex;
    }

    /**
     * long转16进制
     *
     * @param l
     * @return
     */
    public static String longToHex(long l) {
        String hex;
        byte[] bytes = long2bytes(l);
        hex = bytes2hex(bytes);
        return hex;
    }

    /**
     * int转16进制
     *
     * @param i
     * @return
     */
    public static String intToHex(int i) {
        String hex;
        byte[] bytes = int2bytes(i);
        hex = bytes2hex(bytes);
        return hex;
    }

    /**
     * 位置转16进制
     *
     * @param lon
     * @param lat
     * @param alt
     * @return
     */
    public static String positionToHex(double lon, double lat, double alt) {
        //经度
        Long longitude = Math.round(lon * 1.0E6);
        byte[] longitudeBytes = long2bytes(longitude);
        String longitudeHex = bytes2hex(longitudeBytes).substring(8);
        //纬度
        Long latitude = Math.round(lat * 1.0E6);
        byte[] latitudeBytes = long2bytes(latitude);
        String latitudeHex = bytes2hex(latitudeBytes).substring(8);
        //高度
        Long altitude = Math.round(alt);
        byte[] altitudeBytes = long2bytes(altitude);
        String altitudeHex = bytes2hex(altitudeBytes).substring(12);
        //返回16进制
        return longitudeHex + latitudeHex + altitudeHex;
    }

    /*******************************************(16进制转为基本数据类型)******************************************************/

    /**
     * 16进制转int
     *
     * @param hex 16进制字符串
     * @return
     */
    public static int hexToInt(String hex) {
        byte[] bytes = hex2bytes(hex);
        return bytes2int(bytes);
    }

    /**
     * 16进制转换成Long类型
     *
     * @param hex
     * @return
     */
    public static long hexToLong(String hex) {
        byte[] bytes = hex2bytes(hex);
        return bytes2long(bytes);
    }

    /**
     * 16进制转String
     *
     * @param hex
     * @return
     */
    public static String hexToString(String hex) {
        byte[] bytes = hex2bytes(hex);
        return bytes2string(bytes);
    }

    /**
     * 16进制转String
     *
     * @param hex
     * @return
     */
    public static String hexToString(String hex, String charset) {
        byte[] bytes = hex2bytes(hex);
        return bytes2string(bytes, charset);
    }

    /**
     * 将char转换为HexByte
     *
     * @param chr
     * @return
     */
    public static byte castCharToHexByte(char chr) {
        byte chrRet = -1;
        if (chr >= '0' && chr <= '9') {
            chrRet = (byte) chr;
        } else if (chr >= 'A' && chr <= 'F') {
            chrRet = (byte) (chr - 65 + 10);
        } else if (chr >= 'a' && chr <= 'f') {
            chrRet = (byte) (chr - 97 + 10);
        }
        return chrRet;
    }

    /**
     * 异或运算
     *
     * @param datas
     * @return
     */
    public static String getXor(byte[] datas) {
        byte temp = datas[0];
        for (int i = 1; i < datas.length; i++) {
            temp ^= datas[i];
        }
        return Integer.toHexString(temp);
    }

    /**
     * 异或运算
     *
     * @param hex
     * @return
     */
    public static String getXor(String hex) {
        byte[] bytes = hex2bytes(hex);
        int temp = bytes[0];
        for (int i = 1; i < bytes.length; i++) {
            int iData;
            if (bytes[i] < 0) {
                // 变为正数计算
                iData = bytes[i] & 0xff;
            } else {
                iData = bytes[i];
            }
            if (temp < 0) {
                // 变为正数
                temp = temp & 0xff;
            }
            temp ^= iData;
        }
        return ConvertUtil.intToHex(temp).substring(6, 8).toUpperCase();
    }

    /*******************************************(只是单纯的强迫症想分割一下)******************************************************/

    public static byte[] FFtoFE01_Convert(byte[] buf, int offset, int len) {
        ByteBuffer byteBuffer = ByteBuffer.allocate(1024);
        //检查temp_buf指向单元的内容，并将转换后的数据存入
        //buf_des[]数组，函数最后将buf_des[]数组首地址赋给ptr_buf_des，并且返回。
        for (int i = 0; i < buf.length; i++) {
            if (i < offset) {
                byteBuffer.put(buf[i]);
            } else if (i < offset + len) {
                if (buf[i] == (byte) 0xff) {
                    byteBuffer.put((byte) 0xfe);
                    byteBuffer.put((byte) 0x01);
                } else if (buf[i] == (byte) 0xfe) {
                    byteBuffer.put((byte) 0xfe);
                    byteBuffer.put((byte) 0x00);
                } else {
                    byteBuffer.put(buf[i]);
                }
            } else {
                byteBuffer.put(buf[i]);
            }
        }
        byteBuffer.flip();
        byte[] readBuf = new byte[byteBuffer.limit()];
        byteBuffer.get(readBuf);
        return readBuf;
    }

    public static byte[] FE01toFF_Convert(byte[] buf, int offset, int len) {
        ByteBuffer byteBuffer = ByteBuffer.allocate(1024);
        for (int i = 0; i < buf.length; i++) {
            if (i < offset) {
                byteBuffer.put(buf[i]);
            } else if (i < offset + len) {
                if (buf[i] == (byte) 0xfe) {
                    byte temp = buf[i++];
                    temp |= buf[i];
                    byteBuffer.put(temp);
                } else {
                    byteBuffer.put(buf[i]);
                }
            } else {
                byteBuffer.put(buf[i]);
            }
        }
        byteBuffer.flip();
        byte[] readBuf = new byte[byteBuffer.limit()];
        byteBuffer.get(readBuf);
        return readBuf;
    }

    public static String ff2Fe01(String hex) {
        byte[] bytes = hex2bytes(hex);
        //FE转FE00
        int i = 0;
        byte b = (byte) 0xFE;
        while (i < bytes.length) {
            if (bytes[i] == b) {
                byte[] temp1 = new byte[i + 2];
                System.arraycopy(bytes, 0, temp1, 0, i + 1);
                byte[] temp2 = new byte[bytes.length - i - 1];
                System.arraycopy(bytes, i + 1, temp2, 0, bytes.length - i - 1);
                bytes = new byte[temp1.length + temp2.length];
                System.arraycopy(temp1, 0, bytes, 0, temp1.length);
                System.arraycopy(temp2, 0, bytes, temp1.length, temp2.length);
                i++;
            }
            i++;
        }
        i = 0;
        b = (byte) 0xFF;
        while (i < bytes.length) {
            if (bytes[i] == b) {
                bytes[i] = (byte) 0xFE;
                byte[] temp1 = new byte[i + 2];
                System.arraycopy(bytes, 0, temp1, 0, i + 1);
                temp1[i + 1] = (byte) 0x01;
                byte[] temp2 = new byte[bytes.length - i - 1];
                System.arraycopy(bytes, i + 1, temp2, 0, bytes.length - i - 1);
                bytes = new byte[temp1.length + temp2.length];
                System.arraycopy(temp1, 0, bytes, 0, temp1.length);
                System.arraycopy(temp2, 0, bytes, temp1.length, temp2.length);
            }
            i++;
        }
        return ConvertUtil.bytes2hex(bytes).toUpperCase();
    }

    public static String fe012FF(String hex) {
        byte[] bytes = hex2bytes(hex);
        //FE01转FF
        int i = 0;
        byte b1 = (byte) 0xFE;
        byte b2 = (byte) 0x00;
        while (i < bytes.length) {
            if (bytes[i] == b1 && bytes[i + 1] == b2) {
                bytes[i] = (byte) 0xFE;
                byte[] temp1 = new byte[i + 1];
                System.arraycopy(bytes, 0, temp1, 0, i + 1);
                byte[] temp2 = new byte[bytes.length - i - 2];
                System.arraycopy(bytes, i + 2, temp2, 0, bytes.length - i - 2);
                bytes = new byte[temp1.length + temp2.length];
                System.arraycopy(temp1, 0, bytes, 0, temp1.length);
                System.arraycopy(temp2, 0, bytes, temp1.length, temp2.length);
            }
            i++;
        }
        //FE01转FF
        i = 0;
        b1 = (byte) 0xFE;
        b2 = (byte) 0x01;
        while (i < bytes.length) {
            if (bytes[i] == b1 && bytes[i + 1] == b2) {
                bytes[i] = (byte) 0xFF;
                byte[] temp1 = new byte[i + 1];
                System.arraycopy(bytes, 0, temp1, 0, i + 1);
                byte[] temp2 = new byte[bytes.length - i - 2];
                System.arraycopy(bytes, i + 2, temp2, 0, bytes.length - i - 2);
                bytes = new byte[temp1.length + temp2.length];
                System.arraycopy(temp1, 0, bytes, 0, temp1.length);
                System.arraycopy(temp2, 0, bytes, temp1.length, temp2.length);
            }
            i++;
        }
        return ConvertUtil.bytes2hex(bytes).toUpperCase();
    }
}
